/*
 * Copyright (C) 2008 Emweb bvba, Heverlee, Belgium.
 *
 * See the LICENSE file for terms of use.
 */

#include <Wt/WApplication>
#include <Wt/WBreak>
#include <Wt/WContainerWidget>
#include <Wt/WLineEdit>
#include <Wt/WPushButton>
#include <Wt/WText>

#include <Wt/Http/Response>
#include <Wt/WResource>
#include <Wt/WServer>

// c++0x only, for std::bind
// #include <functional>

using namespace Wt;

/*
 * A simple hello world application class which demonstrates how to react
 * to events, read input, and give feed-back.
 */
class HelloApplication : public WApplication
{
public:
  HelloApplication(const WEnvironment& env);

private:
  WLineEdit *nameEdit_;
  WText *greeting_;

  void greet();
};


class MyResource : public WResource
{
public:

  MyResource(std::string url) ;
  ~MyResource() ;

  void handleRequest(const Http::Request& request , Http::Response& response) ;


  static const std::string XML_DOCTYPE ;

  std::string url ;
  std::string ext ;
  std::string type ;
} ;

MyResource::MyResource(std::string url) : WResource(0) , url(url)
{
// printf("MyResource::MyResource() ext=%s\n" , url.substr(url.find_last_of('.') + 1).c_str()) ;

  this->ext  = this->url.substr(this->url.find_last_of('.') + 1) ;
  this->type = (ext == "json") ? "application/json; charset=utf-8" :
               (ext == "xml" ) ? "application/xml; charset=utf-8"  :
                                 "text/plain"                      ;
}

MyResource::~MyResource() { beingDeleted(); }

const std::string MyResource::XML_DOCTYPE = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" ;

void MyResource::handleRequest(const Http::Request& request , Http::Response& response)
{
  response.setMimeType(this->type) ;

  response.out() << ((this->ext == "json") ? "{ data: 'some JSON data' }"                                    :
                     (this->ext == "xml" ) ? XML_DOCTYPE + "<xml-data><data>some XML data</data></xml-data>" :
                                             "some text"                                                     )
                 << std::endl                                                                                ;
}

/*
 * The env argument contains information about the new session, and
 * the initial request. It must be passed to the WApplication
 * constructor so it is typically also an argument for your custom
 * application constructor.
*/
HelloApplication::HelloApplication(const WEnvironment& env) : WApplication(env)
{
printf("HelloApplication::HelloApplication()\n") ;

  setTitle("Hello world");                               // application title
  root()->addWidget(new WText("Your name, please ? "));  // show some text
  nameEdit_ = new WLineEdit(root());                     // allow text input
  nameEdit_->setFocus();                                 // give focus

  WPushButton *button
    = new WPushButton("Greet me.", root());              // create a button
  button->setMargin(5, Left);                            // add 5 pixels margin

  root()->addWidget(new WBreak());                       // insert a line break

  greeting_ = new WText(root());                         // empty text

  /*
   * Connect signals with slots
   *
   * - simple Wt-way
   */
  button->clicked().connect(this, &HelloApplication::greet);

  /*
   * - using an arbitrary function object (binding values with boost::bind())
   */
  nameEdit_->enterPressed().connect
    (boost::bind(&HelloApplication::greet, this));

  /*
   * - using a c++0x lambda:
   */
  // button->clicked().connect(std::bind([=]() {
  //       greeting_->setText("Hello there, " + nameEdit_->text());
  // }));
}

void HelloApplication::greet()
{
  /*
   * Update the text, using text input into the nameEdit_ field.
   */
  greeting_->setText("Hello there, " + nameEdit_->text());
}

WApplication *createApplication(const WEnvironment& env)
{
printf("createApplication()\n") ;
  /*
   * You could read information from the environment to decide whether
   * the user has permission to start a new application
   */
  return new HelloApplication(env);
}


int main(int argc, char **argv)
{
printf("main()\n") ;

  try
  {
    // instantiate server object explicitly in order to have multiple entry points
    // Only the wthttpd connector currently supports multiple entry points.
    // use argv[0] as the application name to match a suitable entry
    // in the Wt configuration file, and use the default configuration
    // file (which defaults to /etc/wt/wt_config.xml unless the environment
    // variable WT_CONFIG_XML is set) - WTHTTP_CONFIGURATION is e.g. "/etc/wt/wthttpd"
    WServer    server      (argc , argv , WTHTTP_CONFIGURATION) ;
    MyResource jsonResource("/data.json") ;
    MyResource xmlResource ("/data.xml" ) ;
    MyResource rawResource ("/data.txt" ) ;

    server.addResource(&jsonResource , jsonResource.url) ;
    server.addResource(&xmlResource  , xmlResource .url) ;
    server.addResource(&rawResource  , rawResource .url) ;
    server.addEntryPoint(Application , boost::bind(&createApplication , _1)) ;

    server.run() ;
  }
  catch (WServer::Exception& e) { std::cerr <<                  e.what() << std::endl ; }
  catch (std::exception     &e) { std::cerr << "exception: " << e.what() << std::endl ; }

  /*
   * Your main method may set up some shared resources, but should then
   * start the server application (FastCGI or httpd) that starts listening
   * for requests, and handles all of the application life cycles.
   *
   * The last argument to WRun specifies the function that will instantiate
   * new application objects. That function is executed when a new user surfs
   * to the Wt application, and after the library has negotiated browser
   * support. The function should return a newly instantiated application
   * object.
   */
//   return WRun(argc, argv, &createApplication);
}

